function _ctDiffLcs(a, b) {
var m = a.length, n = b.length;
var dp = new Array(m + 1);
for (var i = 0; i <= m; i++) dp[i] = new Int32Array(n + 1);
for (var i = 1; i <= m; i++) {
for (var j = 1; j <= n; j++) {
if (a[i-1] === b[j-1]) dp[i][j] = dp[i-1][j-1] + 1;
else dp[i][j] = dp[i-1][j] >= dp[i][j-1] ? dp[i-1][j] : dp[i][j-1];
}
}
return dp;
}
function _ctDiffOps(aText, bText) {
var a = (aText || '').split('\n');
var b = (bText || '').split('\n');
var dp = _ctDiffLcs(a, b);
var i = a.length, j = b.length;
var ops = [];
while (i > 0 && j > 0) {
if (a[i-1] === b[j-1]) { ops.push({op:'=', text:a[i-1]}); i--; j--; }
else if (dp[i-1][j] >= dp[i][j-1]) { ops.push({op:'-', text:a[i-1]}); i--; }
else { ops.push({op:'+', text:b[j-1]}); j--; }
}
while (i > 0) { ops.push({op:'-', text:a[i-1]}); i--; }
while (j > 0) { ops.push({op:'+', text:b[j-1]}); j--; }
ops.reverse();
return ops;
}
function _ctEscDiff(s) {
return (s == null ? '' : String(s)).replace(/[&<>]/g, function(c){
return ({'&':'&','<':'<','>':'>'})[c];
});
}
function _ctRunDiff() {
var aEl = document.getElementById('diff-input-a');
var bEl = document.getElementById('diff-input-b');
var outEl = document.getElementById('diff-output');
var statsEl = document.getElementById('diff-stats');
if (!aEl || !bEl || !outEl) return;
var aVal = aEl.value || '';
var bVal = bEl.value || '';
if (!aVal && !bVal) {
outEl.innerHTML = '(paste text in both boxes to compare)';
if (statsEl) statsEl.textContent = '';
return;
}
var ops = _ctDiffOps(aVal, bVal);
var html = '';
var adds = 0, dels = 0;
for (var k = 0; k < ops.length; k++) {
var o = ops[k];
if (o.op === '+') { html += '+ ' + _ctEscDiff(o.text) + '\n'; adds++; }
else if (o.op === '-') { html += '- ' + _ctEscDiff(o.text) + '\n'; dels++; }
else { html += ' ' + _ctEscDiff(o.text) + '\n'; }
}
outEl.innerHTML = html || '(both texts are identical)';
if (statsEl) {
if (adds === 0 && dels === 0) statsEl.textContent = 'texts are identical';
else statsEl.textContent = adds + ' added, ' + dels + ' removed';
}
}
function convert(input) {
_ctRunDiff();
return '';
}
$(function(){
$('#diff-input-a, #diff-input-b').on('input change', function(){ _ctRunDiff(); });
setTimeout(_ctRunDiff, 50);
});
var _loadedScripts = {};
function loadScriptPromise(url) {
if (_loadedScripts[url]) return _loadedScripts[url];
_loadedScripts[url] = new Promise(function (resolve, reject) {
var s = document.createElement('script');
s.src = url;
s.onload = resolve;
s.onerror = reject;
document.head.appendChild(s);
});
return _loadedScripts[url];
}
function replaceAll(find, replace, str) {
return str.replace(new RegExp(find, 'g'), replace);
}
function beautify(str) {
var result = '';
var length = str.length;
var i = 0;
var braceCountLeft = 0;
var braceCountRight = 0;
var withinQuotes = false;
while (i < length) {
var c = str[i];
if (c == '"' && (i == 0 || c[i - 1] != '\\')) {
// non-escaped quotes
withinQuotes = !withinQuotes;
}
if (!withinQuotes && (c == '}' || c == '{' || c == ',')) {
console.log('Start####' + result);
// look back and remove carriage returns and whitespace that are already there
var resultIndex = result.length - 1;
while (resultIndex >= 0 && (result[resultIndex] == ' ' || result[resultIndex] == '\r' || result[resultIndex] == '\n' || result[resultIndex] == '\t')) {
resultIndex = resultIndex - 1;
result = result.substr(0, resultIndex + 1);
console.log('char ' + result[resultIndex] + '-----' + result + 'zzz ' + result.length + ' ' + resultIndex);
}
if (c == '{') {
braceCountLeft++;
result += c + '\r' + GetTabs(braceCountLeft - braceCountRight);
} else if (c == '}') {
braceCountRight++;
// precede with carriage return
result += '\r' + GetTabs(braceCountLeft - braceCountRight) + c;
} else if (c == ',') {
result += c + '\r' + GetTabs(braceCountLeft - braceCountRight);
}
var nextChar = '';
// advance through whitespace and remove carriage returns that are already there
while (i < length && (str[i + 1] == ' ' || str[i + 1] == '\r' || str[i + 1] == '\n' || str[i + 1] == '\t')) {
i++;
}
} else {
result += str[i];
}
i++;
}
return result;
}
function GetTabs(count) {
var result = '';
for (var i = 0; i < count; i++) {
result += ' ';
}
return result;
}